package main

import (
	"fmt"
	"reflect"
	"strconv"
)

func main() {
	fmt.Println(i(map[string]string{
		"aa": "11",
		"ab": "ac",
	}))
	fmt.Println(i(map[string]interface{}{
		"aa": "11",
		"ac": []string{"123", "abc"},
	}))
	fmt.Println(i(map[string]interface{}{
		"aa": "11",
		"ac": []map[string]string{{"a": "abc"}, {"b": "bac"}},
	}))
	fmt.Println(i("acbd"))
	fmt.Println(i([]string{"a", "b", "c"}))
	fmt.Println(i([]map[string]string{{"a": "abc"}, {"b": "bac"}}))

}

func i(e interface{}) string {
	ev := reflect.ValueOf(e)
	return ii(ev, 0)
}

func ii(ev reflect.Value, deep int) string {
	symbol := ","
	if deep == 0 {
		symbol = "&"
	}
	et := ev.Type()
	switch ev.Kind() {
	case reflect.Interface:
		return ii(reflect.ValueOf(ev.Interface()), deep+1)
	case reflect.Ptr:
		return ii(ev.Elem(), deep+1)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.Itoa(int(ev.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return strconv.Itoa(int(ev.Uint()))
	case reflect.Float32, reflect.Float64:
		return strconv.Itoa(int(ev.Float()))
	case reflect.String:
		original := ev.String()
		if deep != 0 {
			return original
		}
		var str string

		for i, v := range original {
			str += "&" + strconv.Itoa(i) + "=" + string(v)
		}
		return str[1:]

	case reflect.Struct:
		var str string
		for i := 0; i < et.NumField(); i++ {
			ft := et.Field(i)
			f := ev.Field(i)
			str += symbol + ft.Name + "=" + ii(f, deep+1)
		}
		if deep == 0 {
			return str[1:]
		}
		return "{" + str[1:] + "}"
	case reflect.Array, reflect.Slice:
		var str string
		for i := 0; i < ev.Len(); i++ {
			v := ev.Index(i)
			if deep == 0 {
				str += symbol + strconv.Itoa(i) + "=" + ii(v, deep+1)
			} else {
				str += symbol + ii(v, deep+1)
			}
		}
		return str[1:]
	case reflect.Map:
		var str string
		keys := ev.MapKeys()
		for i := 0; i < len(keys); i++ {
			v := ev.MapIndex(keys[i])
			str += symbol + keys[i].String() + "=" + ii(v, deep+1)
		}
		if deep == 0 {
			return str[1:]
		}
		return "{" + str[1:] + "}"
	}
	return ""
}

//function i(e) {
//	var t = [];
//	for (var n in e)
//		if (e[n] || 0 === e[n] || "0" === e[n] || !1 === e[n])
//			if (e[n] instanceof Object && !(e[n] instanceof Array)) {
//				if (e[n] !== {} && 0 !== Object.keys(e[n]).length) {
//					var a = "{".concat(i(e[n]), "}"),
//					o = n + "=" + a;
//					t.push(o);
//				}
//			} else if (e[n] instanceof Array) {
//				var r = e[n];
//				if (0 !== r.length) {
//					var s = "";
//					for (var u in r)
//						r[u] instanceof Object ? (s = "".concat(s, "{").concat(i(r[u]), "}")): (s += r[u]), u < r.length - 1 && (s += ",");
//					var c = n + "=" + s;
//					t.push(c);
//				}
//			} else {
//				if ("string" === typeof e[n] && "" === e[n].trim()) continue;
//				var A = n + "=" + e[n];
//				t.push(A);
//			}
//	return 0 !== t.length ? ((t = t.sort()), t.join("&")) : "";
//}
